/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package smallsimulator;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.geom.GeneralPath;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Locale;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.ImageOutputStream;

/**
 *
 * @author Old
 */
public class ConstrucaoGrafico {

    private int tipo = 0;
    private int nRegistos = 1;
    private String[] regNomes = new String[1];
    private Color[] colors = new Color[1];
    private ArrayList<Float>[] valores = new ArrayList[1];
    private int picW = 1280;
    private int picH = 1024;
    private BufferedImage bigrafico;
    private Graphics2D g;
    private float[] valorMax = new float[1];
    private int eixoXMax = 100;
    private String eixoYLabel = "eixoX";
    private String eixoXLabel = "eixoY";
    private String tituloGrafico = "Titulo";

    public ConstrucaoGrafico(String tipoDeGrafico) {
        if (tipoDeGrafico.equalsIgnoreCase("pontos")) {
            this.tipo = 0;
        } else if (tipoDeGrafico.equalsIgnoreCase("barras")) {
            this.tipo = 1;
        } else {
            //linha temporal
            this.tipo = 2;
        }

        bigrafico = new BufferedImage(picW, picH, BufferedImage.TYPE_INT_RGB);
        g = bigrafico.createGraphics();
        g.setColor(Color.white);
        g.fillRect(0, 0, picW, picH);
        g.setBackground(new Color(255, 255, 255));


        Object interpolating = RenderingHints.VALUE_INTERPOLATION_BICUBIC;
        Object rendering = RenderingHints.VALUE_RENDER_QUALITY;
        Object colorRendering = RenderingHints.VALUE_COLOR_RENDER_QUALITY;
        Object antialiasing = RenderingHints.VALUE_ANTIALIAS_ON;
        Object dithering = RenderingHints.VALUE_DITHER_ENABLE;

        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, interpolating);
        g.setRenderingHint(RenderingHints.KEY_RENDERING, rendering);
        g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, colorRendering);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antialiasing);
        g.setRenderingHint(RenderingHints.KEY_DITHERING, dithering);

        colors[0] = getRandomColor();
        valorMax[0] = 0;
        valores[0] = new ArrayList<Float>();
    }

    public int getnRegistos() {
        return nRegistos;
    }

    public void setnRegistos(int nRegistos, String[] nomes) {
        this.nRegistos = nRegistos;
        regNomes = new String[nRegistos];
        colors = new Color[nRegistos];
        valorMax = new float[nRegistos];
        valores = new ArrayList[nRegistos];
        for (int i = 0; i < nomes.length; i++) {
            regNomes[i] = nomes[i];
            colors[i] = getRandomColor();
            valorMax[i] = 0;
            valores[i] = new ArrayList<Float>();
        }
    }

    public void renderGrafico() {
        drawEixo();
        drawData();
    }

    private void drawData() {
        if (this.tipo == 0) {
            drawDataDots();
        } else if (this.tipo == 1) {
            drawDataBars();
        } else {
            //linha temporal
            drawDataLines();
        }
    }

    private void drawDataBars() {
    }

    private void drawDataDots() {
        int charspacecount = 0;
        for (int i = 0; i < this.nRegistos; i++) {
            int dezenas = 1;
            float valMaxY = (float) Math.ceil(valorMax[i]) * 2f;
            while (valMaxY > 10) {
                dezenas = dezenas * 10;
                valMaxY = (float) Math.floor(valMaxY / 10);
            }
            valMaxY = valMaxY * dezenas;
            int valMaxX = valores[i].size();
            float relY = 750.0f / valMaxY;
            float relX = 1115.0f / valMaxX;
            g.setColor(colors[i]);
            for (int j = 0; j < valores[i].size(); j++) {
                g.drawLine((int) Math.floor(relX * j) + 110, (int) (790 - Math.floor(relY * ((float) valores[i].get(j)))), (int) Math.floor(relX * j) + 110, (int) (790 - Math.floor(relY * ((float) valores[i].get(j)))));
            }

            g.drawString("" + valMaxY, 10, 40 + 12 * i);
            g.drawString("" + (valMaxY / 2), 10, 405 + 12 * i);
            g.drawString("0", 10, 790 + 12 * i);
            g.drawString("" + (3 * valMaxY / 4), 20, 223 + 12 * i);
            g.drawString("" + (valMaxY / 4), 20, 598 + 12 * i);

            g.drawString("" + valMaxX, 1190, 805 + 12 * i);
            g.drawString("" + (valMaxX / 2), 673, 805 + 12 * i);
            g.drawString("0", 115, 800 + 12 * i);
            g.drawString("" + (3 * valMaxX / 4), 952, 805 + 12 * i);
            g.drawString("" + (valMaxX / 4), 404, 805 + 12 * i);

            g.drawString(regNomes[i], 110 + (charspacecount * 10), 880);
            charspacecount += regNomes[i].length();
        }
    }

    private void drawDataLines() {
        int charspacecount = 0;
        for (int i = 0; i < this.nRegistos; i++) {
            int dezenas = 1;
            float valMaxY = (float) Math.ceil(valorMax[i]) * 2f;
            while (valMaxY > 10) {
                dezenas = dezenas * 10;
                valMaxY = (float) Math.floor(valMaxY / 10);
            }
            valMaxY = valMaxY * dezenas;
            int valMaxX = valores[i].size();
            float relY = 750.0f / valMaxY;
            float relX = 1115.0f / valMaxX;
            g.setColor(colors[i]);

            GeneralPath polyline =
                    new GeneralPath(GeneralPath.WIND_EVEN_ODD, valores[i].size());

            polyline.moveTo(110, 790 - Math.floor(relY * ((float) valores[i].get(0))));

            for (int index = 1; index < valores[i].size(); index++) {
                polyline.lineTo(Math.floor(relX * index) + 110, 790 - Math.floor(relY * ((float) valores[i].get(index))));
            }

            g.draw(polyline);

            g.drawString("" + valMaxY, 10, 40 + 12 * i);
            g.drawString("" + (valMaxY / 2), 10, 405 + 12 * i);
            g.drawString("0", 10, 790 + 12 * i);
            g.drawString("" + (3 * valMaxY / 4), 20, 223 + 12 * i);
            g.drawString("" + (valMaxY / 4), 20, 598 + 12 * i);

            g.drawString("" + valMaxX, 1190, 805 + 12 * i);
            g.drawString("" + (valMaxX / 2), 673, 805 + 12 * i);
            g.drawString("0", 115, 800 + 12 * i);
            g.drawString("" + (3 * valMaxX / 4), 952, 805 + 12 * i);
            g.drawString("" + (valMaxX / 4), 404, 805 + 12 * i);

            g.drawString(regNomes[i], 110 + (charspacecount * 10), 900);
            charspacecount += regNomes[i].length();
        }
    }

    private void drawEixo() {
        g.setColor(Color.black);

        g.drawLine(110, 40, 110, 790);
        g.drawLine(110, 790, 1225, 790);

        g.drawLine(110, 40, 60, 40);
        g.drawLine(110, 790, 60, 790);
        g.drawLine(110, 405, 60, 405);

        g.drawLine(110, 223, 85, 223);
        g.drawLine(110, 598, 85, 598);

        g.drawLine(110, 790, 110, 840);
        g.drawLine(1225, 790, 1225, 840);
        g.drawLine(668, 790, 668, 840);

        g.drawLine(389, 790, 389, 815);
        g.drawLine(947, 790, 947, 815);

        float fontW = ((g.getFontMetrics()).charWidth(".".charAt(0))+(g.getFontMetrics()).charWidth("m".charAt(0)))/2f;
        g.drawString(this.eixoXLabel, this.picW - (this.tituloGrafico.length() * 3), 790+(14*this.nRegistos));
        g.drawString(this.eixoYLabel, 10, 25);
        g.drawString(this.tituloGrafico, (this.picW / 2) - (this.tituloGrafico.length() * 3), 15);
    }

    public void addValores(float val) {
        if (valorMax[0] < val) {
            valorMax[0] = val;
        }
        valores[0].add(val);
    }

    public void addValores(float val, int reg) {
        if (valorMax[reg] < val) {
            valorMax[reg] = val;
        }
        valores[reg].add(val);
    }

    public void addValores(float[] val) {
        for (int i = 0; i < val.length; i++) {
            addValores(val[i]);
        }
    }

    public void addValores(float[] val, int reg) {
        for (int i = 0; i < val.length; i++) {
            addValores(val[i], reg);
        }
    }

    private Color getRandomColor() {
        return new Color((int) (Math.random() * 255), (int) (Math.random() * 255), (int) (Math.random() * 255));
    }

    public String getEixoYLabel() {
        return eixoYLabel;
    }

    public void setEixoYLabel(String eixoYLabel) {
        this.eixoYLabel = eixoYLabel;
    }

    public String getEixoXLabel() {
        return eixoXLabel;
    }

    public void setEixoXLabel(String eixoXLabel) {
        this.eixoXLabel = eixoXLabel;
    }

    public int getEixoXMax() {
        return eixoXMax;
    }

    public void setEixoXMax(int eixoXMax) {
        this.eixoXMax = eixoXMax;
    }

    public String getTituloGrafico() {
        return tituloGrafico;
    }

    public void setTituloGrafico(String tituloGrafico) {
        this.tituloGrafico = tituloGrafico;
    }

    public BufferedImage getBigrafico() {
        return bigrafico;
    }
    
    public BufferedImage scaledGraf(int w, int h){
        int initWi = bigrafico.getWidth();
        int initHe = bigrafico.getHeight();
        System.out.println("initWi:" + initWi + " initHe:"+initHe);

        

            int maxWi = w;
            int maxHe = h;
            int newWi = initWi;
            int newHe = initHe;

            if (initWi > maxWi || initHe > maxHe) {
                float factor = 1f;
                if ((float)maxWi / (float)initWi < (float)maxHe / (float)initHe) {
                    factor = (float)maxWi / (float)initWi;
                } else {
                    factor = (float)maxHe / (float)initHe;
                }
                newWi = (int) Math.round((float)initWi * factor);
                newHe = (int) Math.round((float)initHe * factor);
            }

            BufferedImage bimage = new BufferedImage(newWi, newHe, BufferedImage.TYPE_INT_RGB);
            
            /*if(Utils.getExtension(remove).equalsIgnoreCase("png")||Utils.getExtension(remove).equalsIgnoreCase("gif"))
                bimage = new BufferedImage(newWi, newHe, BufferedImage.TYPE_INT_ARGB);*/

            Graphics2D g2 = bimage.createGraphics();
            
            //background color
            g2.setBackground(new Color(255, 255, 255));

            Object interpolating = RenderingHints.VALUE_INTERPOLATION_BICUBIC;
            Object rendering = RenderingHints.VALUE_RENDER_QUALITY;
            Object colorRendering = RenderingHints.VALUE_COLOR_RENDER_QUALITY;
            Object antialiasing = RenderingHints.VALUE_ANTIALIAS_ON;
            Object dithering = RenderingHints.VALUE_DITHER_ENABLE;

            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, interpolating);
            g2.setRenderingHint(RenderingHints.KEY_RENDERING, rendering);
            g2.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, colorRendering);
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antialiasing);
            g2.setRenderingHint(RenderingHints.KEY_DITHERING, dithering);
            Image scale;
            if ((newWi < 300) || (newHe < 300)) {
                scale = bigrafico.getScaledInstance(newWi, newHe, 16);
            } else {
                scale = bigrafico.getScaledInstance(newWi, newHe, 4);
            }
            g2.drawImage(scale, 0, 0, new Color(255, 255, 255), null);
            
            return bimage;
    }

    public void setBigrafico(BufferedImage bigrafico) {
        this.bigrafico = bigrafico;
    }

    public void saveTo(String saveFile) {
        try {
            File novo = new File(saveFile);
            FileOutputStream fos = new FileOutputStream(novo);
            //ImageWriter writer = (ImageWriter) ImageIO.getImageWritersByFormatName(Utils.getExtension(remove)).next();
            ImageWriter writer = (ImageWriter) ImageIO.getImageWritersByFormatName("jpg").next();
            ImageOutputStream ios = ImageIO.createImageOutputStream(fos);
            writer.setOutput(ios);
            ImageWriteParam iwparam = new JPEGImageWriteParam(Locale.getDefault());
            iwparam.setCompressionMode(2);

            iwparam.setCompressionQuality(0.9F);
            writer.write(null, new IIOImage(this.bigrafico, null, null), iwparam);
            ios.flush();
            writer.dispose();
            ios.close();
            fos.close();
        } catch (Exception e) {
            System.out.print("error creating new file: " + e.getMessage());
        }
    }
}
